// ThreadPool.h
 
#pragma once
 
#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>
 
class ThreadPool
{
private:
    std::vector<std::thread> workers_;          // 工作线程
    std::queue<std::function<void()>>tasks_;    // 任务队列，存放匿名函数
    std::mutex queue_mutex_;                    // 任务队列的互斥锁
    std::condition_variable condition_;         // 条件变量，用来唤醒工作线程
    bool stop_;                                 // 线程池是否正在工作
public:
//构造函数，初始化线程
    ThreadPool(size_t size):stop_(false)
    {
        //创建指定数量的工作线程
        for(size_t i=0;i<size;++i)
        {
            workers_.emplace_back([this]{
                //工作线程的主循环
                for(;;)
                {
                    std::function<void()> task;
 
                    {
                        //锁定互斥锁
                        std::unique_lock<std::mutex> lock(this->queue_mutex_);
                        //等待条件变量（有任务或者线程池终止）
                        this->condition_.wait(lock,[this]{
                            return (this->stop_)||!this->tasks_.empty();
                        });
                        //如果线程池停止且没有任务，则退出循环
                        if(this->stop_&&this->tasks_.empty())
                            return;
                        //取出任务
                        task=std::move(this->tasks_.front());
                        this->tasks_.pop();
                    }
                    //执行任务
                    task();
                }
            });
        }
    }
 
    template <class F,class... Args>
    auto enqueue(F&& f,Args&&... args)
        ->std::future<typename std::result_of<F(Args...)>::type>//std::future<return_type>是一个返回类型,return_type是调用函数F并传递参数Args...后返回的类型,result_of推导返回值类型
    {
        using return_type=typename std::result_of<F(Args...)>::type;
        auto task=std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f),std::forward<Args>(args)...)//智能指针包含任务的函数F、参数Args(通过bind绑定在一起，并使用forward实现完美转发)、返回值return_type（类型已经自动推导了）
        );
        std::future<return_type> res=task->get_future();// 获取future对象，用于获取任务的结果
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            if(stop_)
                throw std::runtime_error("enqueue on stopped ThreadPool.");// 如果线程池已停止，则抛出异常
            tasks_.emplace([task](){
                (*task)();
            });// 将任务（一个lambda，调用packaged_task）推入任务队列
        }
        condition_.notify_one();// 通知条件变量，可能有新任务
        return res;// 返回future对象 
    }
    // 析构函数，停止线程池并等待所有任务完成 
    ~ThreadPool()
    {
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            stop_=true;
        }
        condition_.notify_all();// 通知所有等待的线程
        // 等待所有工作线程完成 
        for(std::thread& worker: workers_)
        {
            if(worker.joinable())
                worker.join();
        }
    }
};